/*!
 * \file Hash.cpp
 * \brief Hash value generator.
 * \author Nus
 * \date 2008/02/15, 23:49
 */

#include "Hash.h"

#define get16bits(_d) \
((((u32)(((const u8*)(_d))[1])) << 8) + (u32)(((const u8*)(_d))[0]))

// Generate hash value.
u32 HashValue::calcHashValue(const s8* str, u32 length)
{
  u32 hash = length, tmp;
  s32 rem;

  if(length == 0 || str == NULL)
    return 0;

  rem = length & 3;
  length >>= 2;

  /* Main loop */
  for (; length > 0; length--) {
    hash += get16bits(str);
    tmp = (get16bits(str + 2) << 11) ^ hash;
    hash = (hash << 16) ^ tmp;
    str += 2 * sizeof(u16);
    hash += hash >> 11;
  }

  /* Handle end cases */
  switch (rem) {
  case 3:
    hash += get16bits(str);
    hash ^= hash << 16;
    hash ^= str[sizeof(u16)] << 18;
    hash += hash >> 11;
    break;
  case 2:
    hash += get16bits(str);
    hash ^= hash << 11;
    hash += hash >> 17;
    break;
  case 1:
    hash += *str;
    hash ^= hash << 10;
    hash += hash >> 1;
  }

  /* Force "avalanching" of final 127 bits */
  hash ^= hash << 3;
  hash += hash >> 5;
  hash ^= hash << 4;
  hash += hash >> 17;
  hash ^= hash << 25;
  hash += hash >> 6;
  
  mValue = hash;

  return hash;
}
